<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting in Qyoto</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, painting, Qt, Qyoto, C#">
<meta name="description" content="In this chapter of the Qyoto tutorial, we will
do some painting.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting in Qyoto</h1>

<p>
In this part of the Qyoto C# programming tutorial we will do some painting. 
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<p>
The <code>QPainter</code> class is instrumental when we do some painting in 
Qyoto. Paint events are received in the <code>OnPaintEvent()</code> method. To 
do custom painting, we must reimplement this method. 
</p>


<h2>Patterns</h2>

<p>
In Qyoto, there are various patterns, that we can use to fill the interiors of 
shapes. 
</p>

<pre class="code">
using System;
using QtCore;
using QtGui;

/**
 * ZetCode Qyoto C# tutorial
 *
 * This program draws nine rectangles.
 * The interiors are filled with
 * different built-in patterns.
 *
 * @author Jan Bodnar
 * website zetcode.com
 * last modified November 2012
 */

public class QyotoApp : QMainWindow 
{
    public QyotoApp() 
    {
        WindowTitle = "Patterns";
        
        PaintEvent += OnPaintEvent;

        Resize(350, 280);
        Move(300, 300);
        Show();
    }

    private void OnPaintEvent(object sender, QEventArgs&lt;QPaintEvent&gt; e)
    {
        QPainter ptr = new QPainter(this);
        DrawPatterns(ptr);
        
        ptr.End();
    }
    
    void DrawPatterns(QPainter ptr) 
    {
        ptr.SetPen(Qt.PenStyle.NoPen);

        ptr.SetBrush(Qt.BrushStyle.HorPattern);
        ptr.DrawRect(10, 15, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.VerPattern);
        ptr.DrawRect(130, 15, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.CrossPattern);
        ptr.DrawRect(250, 15, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.Dense7Pattern);
        ptr.DrawRect(10, 105, 90, 60);
        
        ptr.SetBrush(Qt.BrushStyle.Dense6Pattern);
        ptr.DrawRect(130, 105, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.Dense5Pattern);
        ptr.DrawRect(250, 105, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.BDiagPattern);
        ptr.DrawRect(10, 195, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.FDiagPattern);
        ptr.DrawRect(130, 195, 90, 60);

        ptr.SetBrush(Qt.BrushStyle.DiagCrossPattern);
        ptr.DrawRect(250, 195, 90, 60);
    }

    [STAThread]
    public static int Main(String[] args) 
    {
        new QApplication(args);
        new QyotoApp();
        return QApplication.Exec();
    }
}
</pre>

<p>
In the code example, we will draw nine rectangles and fill them with
different brush patterns. 
</p>

<pre class="explanation">
PaintEvent += OnPaintEvent;
</pre>

<p>
Drawing is performed in a paint event. We plug the OnPaintEvent() method to
the paint event.
</p>

<pre class="explanation">
private void OnPaintEvent(object sender, QEventArgs&lt;QPaintEvent&gt; e)
{
    QPainter ptr = new QPainter(this);
    DrawPatterns(ptr);
    
    ptr.End();
}
</pre>

<p>
When the window area needs to be redrawn, the <code>OnPaintEvent()</code> method
is called. This happens, when we resize the window, maximize it or minimize it etc. 
Inside this method, we create the <code>QPainter</code> object. This object is 
used to do all painting in Qyoto. The painting itself is delegated to the 
<code>DrawPatterns()</code> method. The <code>End()</code> method releases 
resources used when doing painting.
</p>

<pre class="explanation">
ptr.SetPen(Qt.PenStyle.NoPen);
</pre>

<p>
The pen object is used to draw outlines of the shapes. In our example
we will not use a pen. 
</p>

<pre class="explanation">
ptr.SetBrush(Qt.BrushStyle.HorPattern);
</pre>

<p>
We set a horizontal pattern as a brush. 
</p>

<pre class="explanation">
ptr.DrawRect(10, 15, 90, 60);
</pre>

<p>
We draw a rectangle, with the current pen and brush.
The first two parameters of the method are the x, y coordinates.
The last two parameters are the width and height of the rectangle. 
</p>


<img src="/img/gui/sharpqyoto/patterns.png" alt="Patterns">
<div class="figure">Figure: Patterns</div>


<h2>Shapes</h2>

<p>
The Qyoto painting API can draw various shapes. The following programming code 
example will show some of them. 
</p>

<pre class="code">
using System;
using System.Collections.Generic;
using QtGui;
using QtCore;

/**
 * ZetCode Qyoto C# tutorial
 *
 * This program draws basic shapes
 * available in Qyoto.
 *
 * @author Jan Bodnar
 * website zetcode.com
 * last modified November 2012
 */

public class QyotoApp : QMainWindow 
{    
    public QyotoApp() 
    {
        WindowTitle = "Shapes";

        PaintEvent += OnPaintEvent;
        
        Resize(350, 280);
        Move(300, 300);
        Show();
    }

    private void OnPaintEvent(object sender, QEventArgs&lt;QPaintEvent&gt; e)
    {
        QPainter ptr = new QPainter(this);
        DrawShapes(ptr);
        
        ptr.End();
    }
    
    void DrawShapes(QPainter ptr) 
    {
        ptr.SetRenderHint(QPainter.RenderHint.Antialiasing);
        ptr.Pen = new QPen(new QBrush(new QColor("Gray")), 1);
        ptr.Brush = new QColor("Gray");

        QPainterPath path1 = new QPainterPath();

        path1.MoveTo(5, 5);
        path1.CubicTo(40, 5,  50, 50,  99, 99);
        path1.CubicTo(5, 99,  50, 50,  5, 5);
        ptr.DrawPath(path1);

        ptr.DrawPie(130, 20, 90, 60, 30*16, 120*16);
        ptr.DrawChord(240, 30, 90, 60, 0, 16*180);
        ptr.DrawRoundRect(20, 120, 80, 50);

        List&lt;QPoint&gt; points = new List&lt;QPoint&gt;();
        points.Add(new QPoint(130, 140));
        points.Add(new QPoint(180, 170));
        points.Add(new QPoint(180, 140));
        points.Add(new QPoint(220, 110));
        points.Add(new QPoint(140, 100));

        QPolygon polygon = new QPolygon(points);
        ptr.DrawPolygon(polygon);

        ptr.DrawRect(250, 110, 60, 60);

        QPointF baseline = new QPointF(20, 250);
        QFont font = new QFont("Georgia", 55);
        QPainterPath path2 = new QPainterPath();
        path2.AddText(baseline, font, "Q");
        ptr.DrawPath(path2);

        ptr.DrawEllipse(140, 200, 60, 60);
        ptr.DrawEllipse(240, 200, 90, 60);
    }

    [STAThread]    
    public static int Main(String[] args) 
    {
        new QApplication(args);
        new QyotoApp();
        return QApplication.Exec();
    }
}
</pre>

<p>
In this code example, we draw nine different shapes on the window. A complex 
path, a pie, a chord, a rounded rectangle, a polygon, a rectangle, a character 
based shape, a circle and an ellipse. 
</p>

<pre class="explanation">
ptr.SetRenderHint(QPainter.RenderHint.Antialiasing);
</pre>

<p>
We use antialiasing in the example. Antialiased shapes look better, but it takes 
more time to draw them. 
</p>

<pre class="explanation">
ptr.Pen = new QPen(new QBrush(new QColor("Gray")), 1);
ptr.Brush = new QColor("Gray");
</pre>

<p>
We use a dark gray pen and brush to draw the shapes. 
</p>

<pre class="explanation">
QPainterPath path1 = new QPainterPath();

path1.MoveTo(5, 5);
path1.CubicTo(40, 5,  50, 50,  99, 99);
path1.CubicTo(5, 99,  50, 50,  5, 5);
ptr.DrawPath(path1);
</pre>

<p>
The first complex shape is created with the <code>QPainterPath</code> object. 
The QPainterPath class provides a container for painting operations. A painter 
path is an object composed of a number of graphical building blocks, such as 
rectangles, ellipses, lines, and curves.
</p>

<pre class="explanation">
ptr.DrawPie(130, 20, 90, 60, 30*16, 120*16);
ptr.DrawChord(240, 30, 90, 60, 0, 16*180);
ptr.DrawRoundRect(20, 120, 80, 50);
</pre>

<p>
These three lines draw a pie, a chord and a rounded rectangle. 
</p>

<pre class="explanation">
List&lt;QPoint&gt; points = new List&lt;QPoint&gt;();
points.Add(new QPoint(130, 140));
points.Add(new QPoint(180, 170));
points.Add(new QPoint(180, 140));
points.Add(new QPoint(220, 110));
points.Add(new QPoint(140, 100));

QPolygon polygon = new QPolygon(points);
ptr.DrawPolygon(polygon);
</pre>

<p>
We use a list of five points to create a polygon. 
</p>

<pre class="explanation">
QPointF baseline = new QPointF(20, 250);
QFont font = new QFont("Georgia", 55);
QPainterPath path2 = new QPainterPath();
path2.AddText(baseline, font, "Q");
ptr.DrawPath(path2);
</pre>

<p>
These lines create a character based shape. 
</p>

<pre class="explanation">
ptr.DrawEllipse(140, 200, 60, 60);
ptr.DrawEllipse(240, 200, 90, 60);
</pre>

<p>
These two lines create a circle and an ellipse respectively.
</p>

<img src="/img/gui/sharpqyoto/shapes.png" alt="Shapes">
<div class="figure">Figure: Shapes</div>


<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material.
The easiest way to understand transparency is to imagine a piece of
glass or water. Technically, the rays of light can go through the 
glass and this way we can see objects behind the glass.
</p>

<p>
In computer graphics, we can achieve transparency effects using alpha compositing.
 Alpha compositing is the process of combining an image with a background 
to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com) 
</p>

<pre class="code">
using System;
using QtCore;
using QtGui;

/**
 * ZetCode Qyoto C# tutorial
 *
 * This program draws ten rectangles with 
 * different levels of transparency.
 *
 * @author Jan Bodnar
 * website zetcode.com
 * last modified November 2012
 */

public class QyotoApp : QMainWindow 
{    
    public QyotoApp() 
    {
        WindowTitle = "Transparent rectangles";
        
        PaintEvent += OnPaintEvent;

        Resize(590, 90);
        Move(300, 300);
        Show();
    }

    private void OnPaintEvent(object sender, QEventArgs&lt;QPaintEvent&gt; e)
    {  
        QPainter ptr = new QPainter(this);
        DrawRectangles(ptr);
        
        ptr.End();
    }
    
    void DrawRectangles(QPainter ptr) 
    {
        ptr.SetPen(Qt.PenStyle.NoPen);

        for (int i=1; i&lt;11; i++) 
        {
            ptr.Brush = new QColor(0, 0, 255, i*25);
            ptr.DrawRect(50*i, 20, 40, 40);
        }
    }

    [STAThread]
    public static int Main(String[] args) 
    {
        new QApplication(args);
        new QyotoApp();
        return QApplication.Exec();
    }
}
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>


<pre class="explanation">
ptr.SetPen(Qt.PenStyle.NoPen);
</pre>

<p>
We use no pen. 
</p>

<pre class="explanation">
for (int i=1; i&lt;11; i++) 
{
    ptr.Brush = new QColor(0, 0, 255, i*25);
    ptr.DrawRect(50*i, 20, 40, 40);
}
</pre>

<p>
The last parameter of the QColor object is the alpha transparency value. 
</p>

<img src="/img/gui/sharpqyoto/trect.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>


<h2>Drawing text</h2>

<p>
In the last example, we are going to draw text on the window. 
</p>

<pre class="code">
using System;
using QtCore;
using QtGui;

/**
 * ZetCode Qyoto C# tutorial
 *
 * This program draws text
 * on the window.
 *
 * @author Jan Bodnar
 * website zetcode.com
 * last modified November 2012
 */

public class QyotoApp : QMainWindow 
{    
    public QyotoApp() 
    {
        WindowTitle = "Soulmate";

        PaintEvent += OnPaintEvent;
        
        Resize(370, 240);
        Move(300, 300);
        Show();
    }

    private void OnPaintEvent(object sender, QEventArgs&lt;QPaintEvent&gt; e)
    { 
        QPainter ptr = new QPainter(this);
        DrawLyrics(ptr);
        
        ptr.End();
    }
    
    void DrawLyrics(QPainter ptr) 
    {
        ptr.Brush = new QColor(25, 25, 25);
        ptr.Font = new QFont("Courier", 10);

        ptr.DrawText(new QPoint(20, 30),
                "Most relationships seem so transitory");
        ptr.DrawText(new QPoint(20, 60),
                "They're good but not the permanent one");
        ptr.DrawText(new QPoint(20, 120),
                "Who doesn't long for someone to hold");
        ptr.DrawText(new QPoint(20, 150),
                "Who knows how to love without being told");
        ptr.DrawText(new QPoint(20, 180),
                "Somebody tell me why I'm on my own");
        ptr.DrawText(new QPoint(20, 210),
                "If there's a soulmate for everyone");
    }
    
    [STAThread]
    public static int Main(String[] args) 
    {
        new QApplication(args);
        new QyotoApp();
        return QApplication.Exec();
    }
}
</pre>

<p>
We draw a song lyrics on the window. 
</p>

<pre class="explanation">
ptr.Font = new QFont("Courier", 10);
</pre>

<p>
We set a Courier font for our text. 
</p>

<pre class="explanation">
ptr.DrawText(new QPoint(20, 30),
        "Most relationships seem so transitory");
</pre>

<p>
The <code>DrawText()</code> method is used
to draw the text at x=20, y=30.
</p>

<img src="/img/gui/sharpqyoto/soulmate.png" alt="Drawing text">
<div class="figure">Figure: Drawing text</div>

<p>
In this part of the Qyoto C# programming tutorial, we did some painting.
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br>

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified November 1, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

